package shake.deployment;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class URLScanner {

	public long lastModifiyTime = -1;;

	public long getLastModifiyTime() {
		return lastModifiyTime;
	}

	public void scanResources(String[] resources, ClassLoader loder) {
		Set<String> paths = new HashSet<String>();
		for (String resourceName : resources) {
			try {
				Enumeration<URL> urlEnum = loder.getResources(resourceName);
				while (urlEnum.hasMoreElements()) {
					String urlPath = urlEnum.nextElement().getFile();
					urlPath = URLDecoder.decode(urlPath, "UTF-8");
					if (urlPath.startsWith("file:")) {
						urlPath = urlPath.substring(5);
					}
					if (urlPath.indexOf('!') > 0) {
						urlPath = urlPath.substring(0, urlPath.indexOf('!'));
					} else {
						File dirOrArchive = new File(urlPath);
						if (resourceName != null
								&& resourceName.lastIndexOf('/') > 0) {
							// for META-INF/components.xml
							dirOrArchive = dirOrArchive.getParentFile();
						}
						urlPath = dirOrArchive.getParent();
					}
					paths.add(urlPath);
				}
			} catch (IOException ioe) {
				throw new RuntimeException(ioe);
			}
		}
		handle(paths, loder);
	}

	private void handle(Set<String> paths, ClassLoader loader) {
		for (String urlPath : paths) {
			try {
				File file = new File(urlPath);
				if (lastModifiyTime < file.lastModified()) {
					lastModifiyTime = file.lastModified();
				}
				if (file.isDirectory()) {
					handleDirectory(file, null, loader);
				} else {
					handleArchiveByFile(file, loader);
				}
			} catch (IOException ioe) {
				throw new RuntimeException(ioe);
			}
		}
	}

	private void handleArchiveByFile(File file, ClassLoader loader)
			throws IOException {
		ZipFile zip = new ZipFile(file);
		Enumeration<? extends ZipEntry> entries = zip.entries();
		while (entries.hasMoreElements()) {
			ZipEntry entry = entries.nextElement();
			String name = entry.getName();
			handleItem(name, loader);
		}
	}

	private void handleDirectory(File file, String path, ClassLoader loader) {
		for (File child : file.listFiles()) {

			if (lastModifiyTime < child.lastModified()) {
				lastModifiyTime = child.lastModified();
			}

			String newPath = path == null ? child.getName() : path + '/'
					+ child.getName();
			if (child.isDirectory()) {
				handleDirectory(child, newPath, loader);
			} else {
				handleItem(newPath, loader);
			}
		}
	}

	protected void handleItem(String name, ClassLoader loader) {
	};

	// public static void main(String[] args) {
	// new URLScanner().scanDirectories(new File[] { new File("lib") });
	// new URLScanner().scanResources(new String[] { "org" }, Thread
	// .currentThread().getContextClassLoader());
	//
	// }

}
